﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;


namespace MH
{
    public class Script
    {
        public Script(Game g)
        {
            game = g;
            OnKeyboardEvent = new KeyboardEvent(OnKeyboardEventCode);
            OnMouseEvent = new MouseEvent(OnMouseEventCode);
            OnGamepadEvent += new GamepadEvent(OnGamepadEventCode);
        }

        Scene

        event KeyboardEvent OnKeyboardEvent;
        event MouseEvent OnMouseEvent;
        event GamepadEvent OnGamepadEvent;
        internal void NotifyKeyboardEvent(int key, KeyboardState ks)
        {
            if (!game.IsFocused)
            {
                return;
            }

            OnKeyboardEvent(null, key, ks);
        }
        internal void NotifyMouseEvent(int x, int y, MouseState ms)
        {
            if (!game.IsFocused)
            {
                return;
            }

            OnMouseEvent(null, x, y, ms);
        }
        internal void NotifyGamepadEvent(int sender, int btn, GamepadState gs)
        {
            if (!game.IsFocused)
            {
                return;
            }

            OnGamepadEvent(sender, btn, gs);
        }
        void OnGamepadEventCode(object sender, int btn, GamepadState gs)
        {
        }
        void OnKeyboardEventCode(object sender, int key, KeyboardState ks)
        {
            if (ks == KeyboardState.KeyDown)
            {
                if (!keydown)
                {
                    if (keycode == -1)
                    {
                        keydown = true;
                        isBlocking = false;
                    }
                    else if (keycode == key)
                    {
                        keydown = true;
                        isBlocking = false;
                    }
                }
            }
            else if (ks == KeyboardState.KeyHold)
            {
                if (!keyhold)
                {
                    if (keycode == -1)
                    {
                        keyhold = true;
                        isBlocking = false;
                    }
                    else if (keycode == key)
                    {
                        keyhold = true;
                        isBlocking = false;
                    }
                }
            }
            else if (ks == KeyboardState.KeyUp)
            {
                if (!keyup)
                {
                    if (keycode == -1)
                    {
                        keyup = true;
                        isBlocking = false;
                    }
                    else if (keycode == key)
                    {
                        keyup = true;
                        isBlocking = false;
                    }
                }
            }
        }
        void OnMouseEventCode(object sender, int x, int y, MouseState ms)
        {
        }
        bool keydown = true;
        bool keyup = true;
        bool keyhold = true;
        int keycode;

        bool isBlocking;
        Game game;
        bool isDelaying
        {
            get
            {
                if (game.RunningTotalSeconds - delayStartTime > delayDuration)
                {
                    return false;
                }
                return true;
            }
        }
        double delayStartTime;
        double delayDuration = 0;
        void delay(int msec)
        {
            if (isDelaying)
            {
                delayDuration += msec / 1000.0;
            }
            else
            {
                delayStartTime = game.RunningTotalSeconds;
                delayDuration = msec / 1000.0;
            }
        }
        public void Heartbeat()
        {
            if (isDelaying)
            {
                return;
            }
            else if (isBlocking)
            {
                return;
            }
            if (cmdque.Count > 0)
            {
                string cmd = cmdque[0];
                cmdque.RemoveAt(0);
                execute(cmd);
            }
            if (cmdqueblock.Count > 0)
            {
                string cmd = cmdqueblock[0];
                cmdqueblock.RemoveAt(0);
                execute(cmd);
            }
        }

        #region for script
        Hashtable vars = new Hashtable();
        List<string> cmdque = new List<string>();
        List<string> cmdqueblock = new List<string>();
        public void AS(string script)
        {
            AppendScript(script, true);
        }
        public void AS(string script, bool block)
        {
            AppendScript(script, block);
        }
        public void IS(string script)
        {
            InsertScript(script, true);
        }
        public void IS(string script, bool block)
        {
            InsertScript(script, block);
        }
        public void AppendScript(string script, bool block)
        {
            string[] lines = script.Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string line in lines)
            {
                if (block)
                {
                    cmdqueblock.Add(line);
                }
                else
                {
                    cmdque.Add(line);
                }
            }
        }
        public void InsertScript(string script, bool block)
        {
            string[] lines = script.Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            int i = 0;
            foreach (string line in lines)
            {
                if (block)
                {
                    cmdqueblock.Insert(i, line);
                }
                else
                {
                    cmdque.Insert(i, line);
                }
                i++;
            }
        }

        void addvar(object key, object value)
        {
            if (vars.Contains(key) == false)
            {
                vars.Add(key, value);
            }
            else
            { 
                vars[key]=value;
            }
        }

        void execute(string cmd)
        {
            cmd = cmd.ToLower();
            string[] words = cmd.Split(new string[] { " ", "," }, StringSplitOptions.RemoveEmptyEntries);
            //if (vars.ContainsKey(words[0]))
            //{

            //}
            //else
            {
                if (words[0] == "if")
                {
                    object value = vars[words[1]];
                    if (words[2] == "=")
                    {
                        if ((int)value == int.Parse(words[3]))
                        {
                            string[] words2 = new string[words.Length - 4];
                            for (int i = 0; i < words2.Length; i++)
                            {
                                words2[i] = words[i + 4];
                            }
                            words = words2;
                        }
                    }
                }
                if (words[0] == "roll")
                {
                    int low = int.Parse(words[1]);
                    int high = int.Parse(words[2]);
                    int v = Util.Roll(low, high);
                    addvar(words[3], v);
                }                
                else if (words[0] == "shock")
                {
                    int time = int.Parse(words[1]);
                    game.SceneCOM.ShockScreen(time);
                }
                else if (words[0] == "delay")
                {
                    int len = int.Parse(words[1]);
                    delay(len);
                }
                else if (words[0] == "fallout")
                {
                    int time = int.Parse(words[1]);
                    game.SceneCOM.FallOutSceen(time);
                }
                else if (words[0] == "fallin")
                {
                    int time = int.Parse(words[1]);
                    game.SceneCOM.FallInSceen(time);
                }
                else if (words[0] == "setctrl")
                {
                    game.SceneCOM.Controllable = true;
                }
                else if (words[0] == "clrctrl")
                {
                    game.SceneCOM.Controllable = false;
                }
                else if (words[0] == "msg")
                {
                    //int time = int.Parse(words[1]);
                    //int x = int.Parse(words[2]);
                    //int y = int.Parse(words[3]);
                    //game.Graph.DrawText(words[4], Color.White, game.Option.Font, true, new Vector3(x, y, 0));
                }
                else if (words[0] == "var")
                {
                    if (vars.Contains(words[1]) == false)
                    {
                        vars.Add(words[1], null);
                    }
                }
                else if (words[0] == "full")
                {
                    game.GoFullScreen();
                }
                else if (words[0] == "block")
                {
                    if (words[1] == "until")
                    {
                        if (words[2] == "key")
                        {
                            if (words[3] == "any")
                            {
                                keycode = -1;
                                if (words[4] == "up")
                                {
                                    isBlocking = true;
                                    keyup = false;
                                }
                                else if (words[4] == "down")
                                {
                                    isBlocking = true;
                                    keydown = false;
                                }
                                else if (words[4] == "hold")
                                {
                                    isBlocking = true;
                                    keyhold = false;
                                }
                            }
                            else
                            {
                                keycode = int.Parse(words[3]);
                                if (words[4] == "up")
                                {
                                    isBlocking = true;
                                    keyup = false;
                                }
                                else if (words[4] == "down")
                                {
                                    isBlocking = true;
                                    keydown = false;
                                }
                                else if (words[4] == "hold")
                                {
                                    isBlocking = true;
                                    keyhold = false;
                                }
                            }
                        }
                    }
                }
                else if (words[0] == "win")
                {
                    game.GoWindowed();
                }
                else if (words[0] == "exit")
                {
                    game.Exit();
                }
                else if (words[0] == "sound")
                {
                    game.Sound.Load(words[1]);
                    game.Sound.Play();
                }
                //else if (words[0] == game.PC.Name.ToLower())
                //{

                //}
                #region 人物脚本
                else
                {
                    for (int i = 0; i < game.CHRs.Count; i++)
                    {
                        Character chr = game.CHRs[i];
                        if (words[0] == chr.Name.ToLower())
                        {
                            if (words[1] == "say")
                            {
                                try
                                {
                                    chr.Said = words[2];
                                }
                                catch
                                {
                                    chr.Said = "";
                                }
                            }
                            else if (words[1] == "move")
                            {
                                Datagram.PlayerCharacterMoveInfo pcmi;

                                pcmi.Name = words[0];
                                pcmi.MoveSpeed = chr.MoveSpeed;
                                pcmi.Steps = int.Parse(words[3]);

                                if (words[2] == "u")
                                {
                                    pcmi.Direction = Direction.U;
                                    chr.Move(pcmi);
                                }
                                else if (words[2] == "l")
                                {
                                    pcmi.Direction = Direction.L;
                                    chr.Move(pcmi);
                                }
                                else if (words[2] == "d")
                                {
                                    pcmi.Direction = Direction.D;
                                    chr.Move(pcmi);
                                }
                                else if (words[2] == "r")
                                {
                                    pcmi.Direction = Direction.R;
                                    chr.Move(pcmi);
                                }
                            }
                            else if (words[1] == "rdir")
                            {
                                chr.RestoreDirection();
                            }
                        }
                    }
                }
                #endregion
            }
        }
        #endregion

        
    }
}
